package com.eurasia.assignment.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import com.eurasia.assignment.domain.hoj.HOJFullCaseJudgement;
import com.eurasia.assignment.domain.hoj.HOJJudgementStatus;
import com.eurasia.assignment.service.exception.FullCaseJudgementNotFoundException;
import com.eurasia.assignment.service.port.out.HOJFullCaseJudgementPersistencePort;
import com.eurasia.assignment.service.port.out.HOJResourcePort;
import com.eurasia.assignment.service.port.out.HOJSingleCaseJudgementPersistencePort;
import com.eurasia.assignment.service.port.out.dto.ConclusionJudgementResult;
import com.eurasia.assignment.service.port.out.dto.HOJResource;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;

@Service
@RequiredArgsConstructor
public class HOJFullCaseJudgementService {
    private static final Logger log = LoggerFactory.getLogger(HOJFullCaseJudgementService.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private final SecurityContext securityContext;
    
    private final HOJResourcePort hojResourcePort;
    private final HOJSingleCaseJudgementPersistencePort hojResourcePersistencePort;
    private final HOJFullCaseJudgementPersistencePort hojFullCaseJudgementPersistencePort;

    private ObjectMapper customMapper;

    @PostConstruct
    public void init() {
        // 创建一个自定义的ObjectMapper，专门用于灵活解析响应
        customMapper = objectMapper.copy();
        customMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    @SneakyThrows
    public ResponseEntity<String> fetchFullCaseJudgementResult(Long submitId) {
        HOJFullCaseJudgement existingJudgement = hojFullCaseJudgementPersistencePort
                .findBySubmitId(submitId)
                .orElseThrow(()->new FullCaseJudgementNotFoundException(submitId.toString()));

        if(null == existingJudgement.getSummarizedResult()) {
            ResponseEntity<String> response = hojResourcePort.fetchFullCaseJudgementConclusionResult(submitId);


            TypeReference<HOJResource<ConclusionJudgementResult>> typeRef = new TypeReference<>() {};
            HOJResource<ConclusionJudgementResult> result = customMapper.readValue(response.getBody(), typeRef);
            HOJJudgementStatus status = mapToHOJSubmissionStatus(result.getData().getSubmission().getStatus());

            if(status == HOJJudgementStatus.JUDGING) {
                return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(response.getBody());
            }

            existingJudgement.setStatus(status);
            existingJudgement.setSummarizedResult(response.getBody());
            existingJudgement.setSubmitRequest(response.getBody());

            HOJFullCaseJudgement saved = hojFullCaseJudgementPersistencePort.save(existingJudgement);
            return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(saved.getSummarizedResult());
        }

        return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(existingJudgement.getSummarizedResult());
    }

    public ResponseEntity<String> fetchFullCaseJudgementDetailedResult(Long submitId) {
        HOJFullCaseJudgement existingJudgement = hojFullCaseJudgementPersistencePort
                .findBySubmitId(submitId)
                .orElseThrow(()->new FullCaseJudgementNotFoundException(submitId.toString()));

        if(null == existingJudgement.getDetailedResult()) {
            ResponseEntity<String> response = hojResourcePort.fetchFullCaseJudgementDetailedResult(submitId);
            //
            existingJudgement.setDetailedResult(response.getBody());

            HOJFullCaseJudgement saved = hojFullCaseJudgementPersistencePort.save(existingJudgement);
            return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(saved.getDetailedResult());
        }
        return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(existingJudgement.getDetailedResult());
    }
    
    /**
     * 将判题系统的status code映射到HOJSubmissionStatus枚举
     */
    private HOJJudgementStatus mapToHOJSubmissionStatus(int statusCode) {
        switch (statusCode) {
            case 6:
                return HOJJudgementStatus.JUDGING;
            case 0:
                return HOJJudgementStatus.ACCEPTED; // passed
            case -1:
                return HOJJudgementStatus.WRONG_ANSWER; // wrong_answer
            case -2:
                return HOJJudgementStatus.COMPILE_ERROR; // compile_error
            case -3:
                return HOJJudgementStatus.RUNTIME_ERROR; // runtime_error
            case -4:
                return HOJJudgementStatus.TIME_LIMIT_EXCEEDED; // time_limit_exceeded
            case -5:
                return HOJJudgementStatus.MEMORY_LIMIT_EXCEEDED; // memory_limit_exceeded
            default:
                return HOJJudgementStatus.FAILED; // failed
        }
    }
}
